package com.flxz.aiaccount.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flxz.aiaccount.dto.ParseRequest;
import com.flxz.aiaccount.dto.ParseResponse;
import com.flxz.aiaccount.service.AiParseService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;

@Service
public class AiParseServiceImpl implements AiParseService {

    @Value("${ai.deepseek.api-key:sk-26cb5eb0b3d744a39e38871c6c19c53d}")
    private String apiKey;

    @Value("${ai.deepseek.api-url:https://api.deepseek.com/v1/chat/completions}")
    private String apiUrl;

    private final RestTemplate restTemplate = new RestTemplate();
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public ParseResponse parseText(ParseRequest request) {
        if (request == null || !StringUtils.hasText(request.getText())) {
            throw new IllegalArgumentException("text 不能为空");
        }
        if (!StringUtils.hasText(apiKey)) {
            throw new IllegalStateException("未配置 ai.deepseek.api-key");
        }

        String systemPrompt = "你是一个中文记账助手。解析用户输入为严格JSON格式（不要任何多余文本）。\n" +
                "字段说明：\n" +
                "- type: 'income'（收入）或 'expense'（支出）\n" +
                "- categoryName: 中文分类名（支出：餐饮/交通/购物/娱乐/医疗/住房/教育/其他；收入：工资/奖金/投资/兼职/其他）\n" +
                "- amount: 数字（金额，单位元）\n" +
                "- remark: 字符串（备注，可为空）\n" +
                "- date: YYYY-MM-DD（未提供用今天：" + LocalDate.now() + "）\n\n" +
                "判断规则：\n" +
                "- 包含消费、购买、花费、支出、花了、用了等词 → expense\n" +
                "- 包含收入、赚了、发了、收到、奖金、工资等词 → income\n" +
                "- 默认情况 → expense\n\n" +
                "示例：\n" +
                "输入：'可乐，3元' → {\"type\":\"expense\",\"categoryName\":\"餐饮\",\"amount\":3,\"remark\":\"\",\"date\":\"" + LocalDate.now() + "\"}\n" +
                "输入：'工资8000' → {\"type\":\"income\",\"categoryName\":\"工资\",\"amount\":8000,\"remark\":\"\",\"date\":\"" + LocalDate.now() + "\"}\n" +
                "输入：'打车20' → {\"type\":\"expense\",\"categoryName\":\"交通\",\"amount\":20,\"remark\":\"\",\"date\":\"" + LocalDate.now() + "\"}\n\n" +
                "只输出JSON，不要解释。";

        Map<String, Object> body = new HashMap<>();
        body.put("model", "deepseek-chat");
        body.put("temperature", 0.2);
        body.put("messages", new Object[] {
                mapOf("role", "system", "content", systemPrompt),
                mapOf("role", "user", "content", request.getText())
        });

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setBearerAuth(apiKey);

        ResponseEntity<String> resp = restTemplate.exchange(apiUrl, HttpMethod.POST, new HttpEntity<>(body, headers), String.class);
        if (resp.getStatusCode().is2xxSuccessful() && resp.getBody() != null) {
            try {
                JsonNode root = objectMapper.readTree(resp.getBody());
                JsonNode msg = root.path("choices").path(0).path("message").path("content");
                if (msg.isMissingNode() || msg.isNull()) {
                    throw new IllegalStateException("AI 返回为空");
                }
                // DeepSeek 可能返回带代码块或多余文本，尝试提取 JSON
                String content = msg.asText().trim();
                System.out.println("AI 原始返回: " + content); // 调试日志
                
                String json = extractJson(content);
                System.out.println("提取的JSON: " + json); // 调试日志
                
                JsonNode j = objectMapper.readTree(json);
                ParseResponse out = new ParseResponse();
                out.setType(j.path("type").asText("expense"));
                out.setCategoryName(j.path("categoryName").asText(""));
                out.setAmount(j.path("amount").isNumber() ? j.path("amount").asDouble() : null);
                out.setRemark(j.path("remark").asText(""));
                out.setDate(j.path("date").asText(LocalDate.now().toString()));
                
                // 更宽松的验证
                if (out.getAmount() == null || out.getAmount() <= 0) {
                    throw new IllegalStateException("未识别有效金额");
                }
                if (!"income".equals(out.getType()) && !"expense".equals(out.getType())) {
                    out.setType("expense"); // 默认为支出
                }
                if (!StringUtils.hasText(out.getCategoryName())) {
                    out.setCategoryName("其他"); // 默认分类
                }
                
                System.out.println("解析结果: " + objectMapper.writeValueAsString(out)); // 调试日志
                return out;
            } catch (Exception e) {
                throw new RuntimeException("解析 AI 返回失败:" + e.getMessage(), e);
            }
        }
        throw new RuntimeException("调用 AI 失败:" + resp.getStatusCode());
    }

    private static Map<String, Object> mapOf(Object... kv) {
        Map<String, Object> m = new HashMap<>();
        for (int i = 0; i < kv.length; i += 2) {
            m.put(String.valueOf(kv[i]), kv[i + 1]);
        }
        return m;
    }

    private String extractJson(String content) {
        String s = content.trim();
        
        // 移除可能的代码块标记
        s = s.replaceAll("```json\\s*", "").replaceAll("```\\s*", "");
        
        // 查找第一个 { 到最后一个 }
        int start = s.indexOf('{');
        int end = s.lastIndexOf('}');
        
        if (start >= 0 && end > start) {
            String json = s.substring(start, end + 1);
            // 简单验证是否为有效JSON
            try {
                objectMapper.readTree(json);
                return json;
            } catch (Exception e) {
                System.out.println("JSON验证失败: " + json + ", 错误: " + e.getMessage());
            }
        }
        
        // 如果都失败了，尝试直接返回
        return s;
    }
}


